﻿using System;
using System.Collections.Generic;
using KuiHuaBaoDian.Services;
using Runtime.Models;
using Runtime.Services.Battle;
using Runtime.Services.Battle.Entity;
using Runtime.Services.BattleAttack;

namespace Runtime.Services.BattleSkill {

    /// <summary>
    /// 战斗技能服务
    /// </summary>
    public interface IDFR_BattleSkillServiceBase {

        public delegate void TriggeredDelegate(IDFR_BattleSkillModelBase skillModel);

        event TriggeredDelegate Triggered;

        /// <summary>
        /// 【战斗】特效实体自动销毁时间
        /// </summary>
        public readonly static F64 BATTLE_HOLDER_AUTO_KILL_TIME = F64.From(4f);

        IDFR_BattleEffectFilter AsEffectFilter();

        /// <summary>
        /// 注册可用的效果类型
        /// </summary>
        /// <param name="type">类型</param>
        void RegisterEffectEntityType(DFR_BattleEntityType type);

        /// <summary>
        /// 添加效果数据
        /// </summary>
        /// <param name="entityInstanceID">效果实例ID</param>
        /// <param name="model">效果数据</param>
        void AddEffectModel(DFR_BattleEntityInstanceID entityInstanceID, IDFR_BattleEffectModelBase model);

        /// <summary>
        /// 移除效果数据
        /// </summary>
        /// <param name="entityInstanceID">效果实例ID</param>
        void RemoveEffectModel(DFR_BattleEntityInstanceID entityInstanceID);

        /// <summary>
        /// 取得效果数据
        /// </summary>
        /// <param name="entityInstanceID">效果实例ID</param>
        IDFR_BattleEffectModelBase GetEffectModel(DFR_BattleEntityInstanceID entityInstanceID);

        /// <summary>
        /// 触发发动攻击时的技能
        /// </summary>
        /// <param name="skillModel">技能</param>
        /// <param name="attacker">攻击者</param>
        /// <param name="selectedAttackTargets">已选的目标</param>
        /// <param name="onTrigger">当触发时的行为</param>
        void TriggerAttackLaunchSkill(IDFR_BattleSkillModelBase skillModel, IDFR_BattleAttacker attacker, IEnumerable<IDFR_BattleAttackTarget> selectedAttackTargets, Action<IDFR_BattleSkillAttacker> onTrigger);

        /// <summary>
        /// 触发击中时的技能，此时还未结算攻击伤害
        /// </summary>
        /// <param name="skillModel">技能</param>
        /// <param name="attackSourceEntityInstanceID">攻击者实例ID</param>
        /// <param name="attackTarget">目标</param>
        void TriggerAttackHitSkill(IDFR_BattleSkillModelBase skillModel, DFR_BattleEntityInstanceID attackSourceEntityInstanceID, IDFR_BattleAttackTarget attackTarget);

        /// <summary>
        /// 触发击杀技能
        /// </summary>
        /// <param name="skillModel">技能</param>
        /// <param name="attackSourceEntityInstanceID">攻击者实例ID</param>
        /// <param name="attackTarget">目标</param>
        void TriggerAttackKillSkill(IDFR_BattleSkillModelBase skillModel, DFR_BattleEntityInstanceID attackSourceEntityInstanceID, IDFR_BattleAttackTarget attackTarget);

        /// <summary>
        /// 给进攻方添加Buff
        /// </summary>
        /// <param name="sourceEntityInstanceID">来源实体实例ID</param>
        /// <param name="effectEntityInstanceID">效果实体实例ID</param>
        /// <param name="index">生效的单元格索引</param>
        bool AddCountdownBuff(DFR_BattleEntityInstanceID sourceEntityInstanceID, DFR_BattleEntityInstanceID effectEntityInstanceID, DFR_BattleCellIndex index);

        /// <summary>
        /// 移动进攻方的Buff效果
        /// </summary>
        /// <param name="sourceEntityInstanceID">进攻方实例ID</param>
        /// <param name="sourceCellIndex">来源单元格索引</param>
        /// <param name="destinationCellIndex">目标单元格索引</param>
        void MoveCountdownBuff(DFR_BattleEntityInstanceID sourceEntityInstanceID, DFR_BattleCellIndex sourceCellIndex, DFR_BattleCellIndex destinationCellIndex);

        /// <summary>
        /// 清除所有进攻方的Buff效果
        /// </summary>
        void ClearCountdownBuff();

        /// <summary>
        /// 给目标添加Debuff效果
        /// </summary>
        /// <param name="targetEntityInstanceID">目标实例ID</param>
        /// <param name="effectEntityInstanceID">效果实例ID</param>
        /// <returns>如果添加成功返回 <c>true</c> </returns>
        bool AddCountdownDebuff(DFR_BattleEntityInstanceID targetEntityInstanceID, DFR_BattleEntityInstanceID effectEntityInstanceID);

        /// <summary>
        /// 为目标移除Buff效果
        /// </summary>
        /// <param name="targetEntityInstanceID">目标实例ID</param>
        /// <param name="buffProviderInstanceID">效果实例ID</param>
        void RemoveBuff(DFR_BattleEntityInstanceID targetEntityInstanceID, DFR_BattleEntityInstanceID buffProviderInstanceID);

        /// <summary>
        /// 为目标移除Buff效果
        /// </summary>
        /// <param name="targetEntityInstanceID">目标实例ID</param>
        /// <param name="buffProvider">Buff</param>
        void RemoveBuff(DFR_BattleEntityInstanceID targetEntityInstanceID, IDFR_BattleBuffProvider buffProvider);

        /// <summary>
        /// 清除目标在影响集合中的Buff，并不会移除Buff
        /// </summary>
        /// <param name="targetEntityInstanceID">目标实例ID</param>
        void ClearBuffInfluence(DFR_BattleEntityInstanceID targetEntityInstanceID);
    }

    /// <summary>
    /// 战斗技能服务
    /// </summary>
    public static class BattleSkillServiceBase {

        /// <summary>
        /// 单例
        /// </summary>
        public static IDFR_BattleSkillServiceBase Instance => m_Instance ??= KHBD.TypeMap.Instantiate<IDFR_BattleSkillServiceBase>();
        private static IDFR_BattleSkillServiceBase m_Instance;
    }

    public abstract partial class DFR_BattleSkillServiceBase : IDFR_BattleSkillServiceBase, IDFR_BattleEffectFilter, IService {

        public event IDFR_BattleSkillServiceBase.TriggeredDelegate Triggered;

        protected void DispatchTriggered(IDFR_BattleSkillModelBase skillModel, DFR_BattleMapPosition mapPosition) {
            var skillHolder = skillModel.AsHolder();
            if (skillHolder.HasModelAsset) {
                BattleServiceBase.Instance.AttachHolder(skillHolder, mapPosition, IDFR_BattleSkillServiceBase.BATTLE_HOLDER_AUTO_KILL_TIME);
            }
            Triggered?.Invoke(skillModel);
        }

        public IDFR_BattleEffectFilter AsEffectFilter() => this;

        void IService.OnApplicationQuit() {
            OnApplicationQuit();
            m_EffectModelDictionary.Clear();
        }

        protected abstract void OnApplicationQuit();

        private IDFR_BattleEffectFilter m_EffectFilter;
        private DFR_BattleEntityType m_EffectEntityType;

        private readonly Dictionary<DFR_BattleEntityInstanceID, IDFR_BattleEffectModelBase> m_EffectModelDictionary = new();
        protected IReadOnlyDictionary<DFR_BattleEntityInstanceID, IDFR_BattleEffectModelBase> EffectModelDictionary => m_EffectModelDictionary;

        protected void Initialize() {
            m_EffectFilter = KHBD.TypeMap.Instantiate<IDFR_BattleEffectFilter>();
        }

        protected void End() {
            Triggered = null;
            if (m_EffectFilter is IDisposable disposable) {
                disposable.Dispose();
                m_EffectFilter = null;
            }
            m_EffectModelDictionary.Clear();
        }

        public void AddEffectModel(DFR_BattleEntityInstanceID entityInstanceID, IDFR_BattleEffectModelBase model) {
            m_EffectModelDictionary.Add(entityInstanceID, model);
        }

        public void RemoveEffectModel(DFR_BattleEntityInstanceID entityInstanceID) {
            m_EffectModelDictionary.Remove(entityInstanceID);
        }

        public IDFR_BattleEffectModelBase GetEffectModel(DFR_BattleEntityInstanceID entityInstanceID) {
            if (m_EffectModelDictionary.ContainsKey(entityInstanceID)) {
                return m_EffectModelDictionary[entityInstanceID];
            }
            return default;
        }

        public void RegisterEffectEntityType(DFR_BattleEntityType type) => m_EffectEntityType = type;

        protected bool IsTrigger(IDFR_BattleSkillModelBase skillModel) => skillModel.TriggerProbability.Value >= F64.One || BattleServiceBase.Instance.Random() < skillModel.TriggerProbability.Value;

        bool IDFR_BattleEffectFilter.IsIgnore(IEnumerable<IDFR_ReadOnlyBattleFusionData.IItem> owner,
                                              IDFR_ReadOnlyBattleFusionData.IItem data,
                                              IReadOnlyCollection<IDFR_ReadOnlyBattleFusionData.IItem> takedItems) {
            if (m_EffectFilter != null && data.EntityInstanceID.ID.Type == m_EffectEntityType) {
                return m_EffectFilter.IsIgnore(owner, data, takedItems);
            }
            return false;
        }

        public abstract void TriggerAttackLaunchSkill(IDFR_BattleSkillModelBase skillModel, IDFR_BattleAttacker attacker, IEnumerable<IDFR_BattleAttackTarget> selectedAttackTargets, Action<IDFR_BattleSkillAttacker> onTrigger);

        public abstract void TriggerAttackHitSkill(IDFR_BattleSkillModelBase skillModel, DFR_BattleEntityInstanceID attackSourceEntityInstanceID, IDFR_BattleAttackTarget attackTarget);

        public abstract void TriggerAttackKillSkill(IDFR_BattleSkillModelBase skillModel, DFR_BattleEntityInstanceID attackSourceEntityInstanceID, IDFR_BattleAttackTarget attackTarget);

        public abstract bool AddCountdownBuff(DFR_BattleEntityInstanceID sourceEntityInstanceID, DFR_BattleEntityInstanceID effectEntityInstanceID, DFR_BattleCellIndex index);

        public abstract void MoveCountdownBuff(DFR_BattleEntityInstanceID sourceEntityInstanceID, DFR_BattleCellIndex sourceCellIndex, DFR_BattleCellIndex destinationCellIndex);

        public abstract void ClearCountdownBuff();

        public abstract bool AddCountdownDebuff(DFR_BattleEntityInstanceID targetEntityInstanceID, DFR_BattleEntityInstanceID effectModelInstanceID);

        public abstract void RemoveBuff(DFR_BattleEntityInstanceID targetEntityInstanceID, DFR_BattleEntityInstanceID buffProviderInstanceID);

        public abstract void RemoveBuff(DFR_BattleEntityInstanceID targetEntityInstanceID, IDFR_BattleBuffProvider buffProvider);

        public abstract void ClearBuffInfluence(DFR_BattleEntityInstanceID targetEntityInstanceID);
    }
}

